/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import util.HibernateUtil;

/**
 *
 * @author duonghung1369
 */
public class BaseDAO<T> {

    protected Session session;
    protected Class<T> type;

    public BaseDAO(Class<T> type) {
        this.type = type;
    }

    /**
     * Open a session and user must manage this session manually.
     * @throws HibernateException
     */
    public void openSession() throws HibernateException {
        session = HibernateUtil.openSession();
    }

    /**
     * Close session if it still open.
     * @throws HibernateException
     */
    public void closeSession() throws HibernateException {
        if(session != null && session.isOpen()){
            session.flush();
            session.close();
        }
    }

    /**
     * Save new entity to database.
     * @param entity
     * @return
     * @throws HibernateException
     */
    public Serializable save(T entity) throws HibernateException {
        Serializable result = null;
        session.beginTransaction();
        result = session.save(entity);
        session.getTransaction().commit();
        return result;
    }

    public void saveOrUpdate(T entity) throws HibernateException, NullPointerException {
        session.beginTransaction();
        session.saveOrUpdate(entity);
        session.getTransaction().commit();
    }

    public T get(Serializable id) throws HibernateException {
        session.beginTransaction();
        return (T) session.get(type, id);
    }

    public T get(Serializable id, Map<String, FetchMode> fetchMode) throws HibernateException, NullPointerException {
        Criteria criteria = session.createCriteria(type);
        String tableName;
        FetchMode mode;
        for(Map.Entry<String, FetchMode> entry : fetchMode.entrySet()){
            tableName = entry.getKey();
            mode = entry.getValue();
            criteria.setFetchMode(tableName, mode);
        }

        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return (T) criteria.add(Restrictions.eq("id", id)).uniqueResult();

    }

    public List<T> all() throws HibernateException {
        session.beginTransaction();
        return session.createCriteria(type).list();
    }

    public void update(T entity) throws HibernateException {
        session.beginTransaction();
        session.update(entity);
        session.getTransaction().commit();
    }

    /**
     * Remove the entity of the specified class with the specified id from the database.
     * @param type
     * @param id
     * @return true if the object is found in the datastore and deleted,
     * false if the item is not found.
     * @throws HibernateException
     */
    public boolean deleteById(Serializable id) throws HibernateException {
        Boolean result = false;
        session.beginTransaction();

        if (id != null) {
            Object entity = session.get(type, id);
            if (entity != null) {
                session.delete(entity);
                result = true;
            }
        } else {
            result = false;
        }

        session.getTransaction().commit();
        return result;
    }

    /**
     * Check object in current session or not.
     * @param o
     * @return true if the object is connected to the current hibernate session.
     */
    public boolean sessionContains(Object o) {
        session.beginTransaction();
        return session.contains(o);
    }

    /**
     * Flushes changes in the hibernate cache to the database.
     */
    public void flush() {
        session.beginTransaction();
        session.flush();
        session.getTransaction().commit();
    }

    /**
     * Refresh the content of the given entity from the current database state.
     * @param entities
     */
    public void refresh(T entity) throws HibernateException {
        session.beginTransaction();
        session.refresh(entity);
        session.getTransaction().commit();
    }

    public Session getSession() {
        return session;
    }

    
}
